撰寫 ViewModel 的單元測試是確保 Android 應用程式品質的重要一環。透過測試,可以及早發現並修復問題,提高應用程式的穩定性。
在 app 的 build.gradle.kts
dependencies {
    ...
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
    
    testImplementation("junit:junit:4.13.2")
    
    // Import the Compose BOM
    implementation(platform("androidx.compose:compose-bom:2023.06.01"))
    implementation("androidx.compose.material:material")
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-tooling-preview")
    // ...
    androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
}
良好的單元測試通常具備下列四種屬性:
在專案的 路徑(test) 新增測試程式
錯誤路徑單元測試
@Test
    fun gameViewModel_IncorrectGuess_ErrorFlagSet() {
        // Given an incorrect word as input
        val incorrectPlayerWord = "and"
        viewModel.updateUserGuess(incorrectPlayerWord)
        viewModel.checkUserGuess()
        val currentGameUiState = viewModel.uiState.value
        // Assert that score is unchanged
        assertEquals(0, currentGameUiState.score)
        // Assert that checkUserGuess() method updates isGuessedWordWrong correctly
        assertTrue(currentGameUiState.isGuessedWordWrong)
    }
測試 UI 的初始狀態
@Test
fun gameViewModel_Initialization_FirstWordLoaded() {
    val gameUiState = viewModel.uiState.value
    val unScrambledWord = getUnscrambledWord(gameUiState.currentScrambledWord)
    // Assert that current word is scrambled.
    assertNotEquals(unScrambledWord, gameUiState.currentScrambledWord)
    // Assert that current word count is set to 1.
    assertTrue(gameUiState.currentWordCount == 1)
    // Assert that initially the score is 0.
    assertTrue(gameUiState.score == 0)
    // Assert that the wrong word guessed is false.
    assertFalse(gameUiState.isGuessedWordWrong)
    // Assert that game is not over.
    assertFalse(gameUiState.isGameOver)
}
猜出所有字詞後測試 UI 狀態-正確
@Test
fun gameViewModel_AllWordsGuessed_UiStateUpdatedCorrectly() {
    var expectedScore = 0
    var currentGameUiState = viewModel.uiState.value
    var correctPlayerWord = getUnscrambledWord(currentGameUiState.currentScrambledWord)
    repeat(MAX_NO_OF_WORDS) {
        expectedScore += SCORE_INCREASE
        viewModel.updateUserGuess(correctPlayerWord)
        viewModel.checkUserGuess()
        currentGameUiState = viewModel.uiState.value
        correctPlayerWord = getUnscrambledWord(currentGameUiState.currentScrambledWord)
        // Assert that after each correct answer, score is updated correctly.
        assertEquals(expectedScore, currentGameUiState.score)
    }
    // Assert that after all questions are answered, the current word count is up-to-date.
    assertEquals(MAX_NO_OF_WORDS, currentGameUiState.currentWordCount)
    // Assert that after 10 questions are answered, the game is over.
    assertTrue(currentGameUiState.isGameOver)
}
測試執行個體生命週期總覽
@Test
    fun gameViewModel_Initialization_FirstWordLoaded() {
        
        val gameUiState = viewModel.uiState.value
        val unScrambledWord = getUnscrambledWord(gameUiState.currentScrambledWord)
        // Assert that current word is scrambled.
        assertNotEquals(unScrambledWord, gameUiState.currentScrambledWord)
        // Assert that current word count is set to 1.
        assertTrue(gameUiState.currentWordCount == 1)
        // Assert that initially the score is 0.
        assertTrue(gameUiState.score == 0)
        // Assert that wrong word guessed is false.
        assertFalse(gameUiState.isGuessedWordWrong)
        // Assert that game is not over.
        assertFalse(gameUiState.isGameOver)
    }
程式碼涵蓋率扮演著重要角色,會決定您必須對應用程式組成類別、方法和程式碼是否充分測試。
Android Studio 提供了本機單元測試工具的測試涵蓋範圍工具,可用於追蹤單元測試所涵蓋應用程式程式碼的百分比和範圍。
在「Project」窗格中的 GameViewModelTest.kt 檔案上按一下滑鼠右鍵,然後選取「Run 'GameViewModelTest' with Coverage」。
在「程式」窗格中的 class GameViewModelTest 左邊按一下滑鼠右鍵,然後選取「Run 'GameViewModelTest' with Coverage」。
就會有結果 GameViewModel 元素,確認涵蓋率百分比為 100%。最終涵蓋率報表

https://developer.android.com/codelabs/basic-android-kotlin-compose-test-viewmodel